//#include "stdafx.h"
#include "LogManager.h"
#include "FileExecutor.h"

using namespace Utility::LoggerLib;

CLogManager::CLogManager()
{
    CreateAllExecutors();
};

CLogManager::~CLogManager()
{
    ClearAllExecutors();
}

void CLogManager::SetLogLevel(unsigned long dwLevel)
{
    m_dwLogLevel = dwLevel;
    m_setLevel.clear();

    if (dwLevel == ALL_LEVEL)
    {
        m_setLevel.insert(DEBUG_LEVEL);
        m_setLevel.insert(ERROR_LEVEL);
        m_setLevel.insert(WARN_LEVEL);
        m_setLevel.insert(INFO_LEVEL);
        return;
    }

    if (dwLevel & DEBUG_LEVEL)
    {
        m_setLevel.insert(DEBUG_LEVEL);
    }

    if(dwLevel & ERROR_LEVEL)
    {
        m_setLevel.insert(ERROR_LEVEL);
    }

    if(dwLevel & WARN_LEVEL)
    {
        m_setLevel.insert(WARN_LEVEL);
    }

    if (dwLevel & INFO_LEVEL)
    {
        m_setLevel.insert(INFO_LEVEL);
    }
}

void CLogManager::SetLogExecutorFlag(unsigned long dwFlag)
{
    m_setActiveExecutors.clear();

    if(dwFlag & CONSOLE_EXECUTOR)
    {
        AddActiveExecutor(CONSOLE_EXECUTOR);
    }

    if (dwFlag & FILE_EXECUTOR)
    {
        AddActiveExecutor(FILE_EXECUTOR);
    }

    if (dwFlag & WIN32DEBUG_EXECUTOR)
    {
        AddActiveExecutor(WIN32DEBUG_EXECUTOR);
    }

    if (dwFlag & SYSEVENT_EXECUTOR)
    {
        AddActiveExecutor(SYSEVENT_EXECUTOR);
    }
}

IExecutor* CLogManager::GetExecutor(ELOGEXECUTOR eType)
{
    ExecutorMap::iterator iter = m_mapExecutors.find(eType);
    return iter == m_mapExecutors.end() ? NULL : iter->second;
}

int CLogManager::Log(ELOGLEVEL eLevel, ELOGMODULE eModule, const wstring& strLog)
{
    LevelSet::iterator iter = m_setLevel.find(eLevel);
    if(iter == m_setLevel.end())
    {
        return 0; 
    }
     
    LoggingEvent event(strLog, eLevel, eModule);
    return InvokeExecutors(event);
}

bool CLogManager::StartAllExecutors()
{
    if(m_setActiveExecutors.empty())
    {
        return false;
    }

    bool bRet = true;
    ExecutorSet::const_iterator iter = m_setActiveExecutors.begin();
    for(; iter!=m_setActiveExecutors.end(); iter++)
    {
        bRet = bRet && ((*iter)->Reopen());
    }

    return bRet;
}

bool CLogManager::StartExecutor(ELOGEXECUTOR eType)
{
    if(m_setActiveExecutors.empty())
    {
        return false;
    }

    ExecutorMap::const_iterator iter = m_mapExecutors.find(eType);
    if(iter == m_mapExecutors.end())
    {
        return false;
    }

    ExecutorSet::const_iterator setIter = m_setActiveExecutors.find(iter->second);
    if(setIter == m_setActiveExecutors.end())
    {
        return false;
    }

    return (*setIter)->Reopen();;
}

void CLogManager::SetLogFilePath(const wstring &strPath)
{
        IExecutor *pExecutor = GetExecutor(FILE_EXECUTOR);
        CFileExecutor *pFileExecutor = dynamic_cast<CFileExecutor*>(pExecutor);
        pFileExecutor->SetFilePath(strPath);
}

int CLogManager::CreateAllExecutors()
{
    IExecutor *pExecutor = new CFileExecutor(wstring(L"FileLog"));
    m_mapExecutors.insert(ExecutorMapVal(FILE_EXECUTOR, pExecutor));

    // Other executors zhwang: to do
    return m_mapExecutors.size();
}

void CLogManager::ClearAllExecutors()
{
    m_setActiveExecutors.clear();

    ExecutorMap::iterator iter = m_mapExecutors.begin();
    for (; iter!=m_mapExecutors.end(); iter++)
    {
        delete iter->second;
        iter->second = NULL;
    }

    m_mapExecutors.clear();
}

int CLogManager::InvokeExecutors(const LoggingEvent& logEvent)
{
    if(m_setActiveExecutors.empty())
    {
        return 0;
    }

    int nFailedCount = 0;
    ExecutorSet::const_iterator iter = m_setActiveExecutors.begin();
    for(; iter!=m_setActiveExecutors.end(); iter++)
    {
        if(!(*iter)->DoLogging(logEvent))
        {
            nFailedCount++;
        }
    }

    return nFailedCount;
}

void CLogManager::AddActiveExecutor(ELOGEXECUTOR eType)
{
    ExecutorMap::iterator iter = m_mapExecutors.find(eType);
    if (iter != m_mapExecutors.end())
    {
        m_setActiveExecutors.insert(iter->second);
    }
}